home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / rpc / rpcDispatch.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  17KB  |  543 lines

  1. /*
  2.  * rpcDispatch.c --
  3.  *
  4.  * The top level rpc dispatch routine.  The dispatcher is responsible for
  5.  * taking a packet from the packet transport level and passing it to the
  6.  * delivery level of the correct process involved in the RPC.  The
  7.  * top-level dispatcher finds the protocol state for the client or server
  8.  * receiving the message and calls the client or server specific dispatch
  9.  * routine.  This file also has the utility routine to copy a message from
  10.  * the network module's buffers into the stub's buffers.
  11.  *
  12.  * Copyright 1985 Regents of the University of California
  13.  * All rights reserved.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/rpc/rpcDispatch.c,v 9.21 92/12/13 18:21:32 mgbaker Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <stdio.h>
  22. #include <bstring.h>
  23. #include <string.h>
  24. #include <dbg.h>
  25. #include <vm.h>
  26.  
  27. #include <rpc.h>
  28. #include <rpcClient.h>
  29. #include <rpcServer.h>
  30. #include <rpcTrace.h>
  31. #include <rpcInt.h>
  32. #include <net.h>
  33.  
  34. #include <recov.h>
  35.  
  36. int ultra;
  37.  
  38. /*
  39.  * Our sprite ID.  It is exported for general use by other modules.
  40.  * This is set by a reverse arp transaction at boot time (see Rpc_Start),
  41.  * or if that fails, by the rpc dispatcher who monitors the clientID field of
  42.  * rpc reply messages (see RpcClientDispatch).  Finally, if neither of
  43.  * those hooks work, a diskfull node will set its address by looking at
  44.  * the disk header (see FsAttachDisk).
  45.  *
  46.  * Important: servers won't respond to requests until their rpc_SpriteID is set.
  47.  */
  48. int    rpc_SpriteID = 0;
  49.  
  50. /*
  51.  * We stop handlling requests during a bad trap that causes us
  52.  * to sync our disks.  If that deadlocks we want to be sure that
  53.  * the RPC system is off so we can't hang other machines.
  54.  */
  55. extern int sys_ErrorSync;
  56.  
  57. /*
  58.  * While testing there may be many version mismatch errors.  If
  59.  * rpc_PrintMismatch is FALSE, then we only report a few of these errors
  60.  * every once in a while.
  61.  */
  62. int mismatchErrors = 0;
  63.  
  64. /*
  65.  * An array of bitmasks is kept for faster comparisions by the dispatcher.
  66.  * Indexed by the total number of fragments in the packet, the array
  67.  * contains a complete bitmask for that many fragments.
  68.  */
  69. unsigned int rpcCompleteMask[17] = {
  70.     0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  71.         0x001F, 0x003F, 0x007F, 0x00FF,
  72.         0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  73.         0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  74. /*
  75.  * Forward declarations.
  76.  */
  77. static Boolean ValidateClient _ARGS_((Net_Interface *interPtr, int protocol,
  78.         Address headerPtr, RpcHdr *rpcHdrPtr));
  79. static void VersionMismatch _ARGS_((Net_Interface *interPtr, int protocol,
  80.         Address headerPtr, RpcHdr *rpcHdrPtr, int packetLength));
  81.  
  82.  
  83.  
  84.  
  85. /*
  86.  *----------------------------------------------------------------------
  87.  *
  88.  * Rpc_Dispatch --
  89.  *
  90.  *      This does some consistency checks on an incoming packet, finds the
  91.  *      protocol state for the packet (either client or server) and then
  92.  *      calls either the server or client dispatch routine.
  93.  *
  94.  *    This still has a few ethernet specfich things that should be fixed.
  95.  *
  96.  * Results:
  97.  *    None.
  98.  *
  99.  * Side effects:
  100.  *    This may drop a packet if various consistency checks fail.
  101.  *
  102.  *----------------------------------------------------------------------
  103.  */
  104. void
  105. Rpc_Dispatch(interPtr, protocol, headerPtr, rpcHdrAddr, packetLength)
  106.     Net_Interface *interPtr;    /* Network interface where we got the packet. */
  107.     int        protocol;    /* Network protocol of packet. */
  108.     Address    headerPtr;    /* Pointer to transport header. */
  109.     Address     rpcHdrAddr;    /* RPC header of packet. */
  110.     int        packetLength;        /* Size of RPC packet. */
  111. {
  112.     register RpcHdr    *rpcHdrPtr; /* RPC header of packet. */
  113.     register int expectedLength;
  114.     extern int ultra;
  115.  
  116.  
  117.     if (ultra) {
  118.     printf("In Rpc_Dispatch\n");
  119.     }
  120.     rpcHdrPtr = (RpcHdr *) rpcHdrAddr;
  121.     if (packetLength < sizeof(RpcHdr)) {
  122.     rpcCltStat.shorts++;
  123.     printf("Rpc_Dispatch: SHORT packet, (%d) less than RpcHdr\n",
  124.                   packetLength, sizeof(RpcHdr));
  125.     printf("Resetting network interface %s\n",
  126.         interPtr->name);
  127.     Net_Reset(interPtr);
  128.     return;
  129.     }
  130.     if (rpcHdrPtr->version == rpc_SwappedVersion) {
  131.     /*
  132.      * Byte swap the packet header and the parameter block.
  133.      */
  134.     if (!RpcByteSwapInComing(rpcHdrPtr, packetLength)) {
  135.         printf("Warning: Rpc_Dispatch failed byte-swap.\n");
  136.         return;
  137.     }
  138.     } else if (rpcHdrPtr->version != rpc_NativeVersion) {
  139.     /*
  140.      * Keep a short list of hosts that aren't talking the
  141.      * right version of RPC.  Attempt to print out one message
  142.      * about this per host, and then keep quiet.
  143.      */
  144.     VersionMismatch(interPtr, protocol, headerPtr, rpcHdrPtr, packetLength);
  145.     return;
  146.     }
  147.     expectedLength =  sizeof(RpcHdr) +
  148.              rpcHdrPtr->paramSize +
  149.              rpcHdrPtr->dataSize;
  150.     if (packetLength < expectedLength) {
  151.     rpcCltStat.shorts++;
  152.     printf("Rpc_Dispatch: SHORT packet, (%d) not (%d), ",
  153.                   packetLength, expectedLength);
  154.     printf("srv %d clt %d rpc %d\n", rpcHdrPtr->serverID,
  155.             rpcHdrPtr->clientID, rpcHdrPtr->command);
  156.     printf("Resetting network interface %s\n",
  157.         interPtr->name);
  158.     Net_Reset(interPtr);
  159.     return;
  160.     } else if (packetLength > expectedLength &&
  161.            packetLength > interPtr->minBytes) {
  162.     /*
  163.      * Short messages (like acks and null replies)
  164.      * get padded to minimum  packet length.  Other messages
  165.      * get padded to 4 byte alignments.
  166.      */
  167.     rpcCltStat.longs++;
  168.     if (packetLength > interPtr->maxBytes) {
  169.         printf("Received oversized packet\n");
  170.         printf("Resetting network interface\n");
  171.         Net_Reset(interPtr);
  172.         return;
  173.     }
  174.     }
  175.  
  176.     RPC_TRACE(rpcHdrPtr, RPC_INPUT, "Input");
  177.  
  178.     if (rpcHdrPtr->flags & RPC_SERVER) {
  179.     register RpcServerState *srvPtr = (RpcServerState *) NIL;
  180.     /*
  181.      * Don't do anything if we don't know who we are.  This occurs
  182.      * at boot time if we get a request before doing reverse ARP.
  183.      * Also, don't do anything in the middle of a panic.  If a host
  184.      * deadlocks trying to enter the debugger, then callback RPCs
  185.      * from file servers should not also hang.
  186.      */
  187.     if (rpc_SpriteID == 0 || sys_ErrorSync) {
  188.         return;
  189.     }
  190.     if (rpcHdrPtr->serverID != RPC_BROADCAST_SERVER_ID &&
  191.         rpcHdrPtr->serverID != rpc_SpriteID) {
  192.         /*
  193.          * A bug, or the Intel chip is wack-o.
  194.          */
  195.         if (rpcHdrPtr->serverID > 0 &&
  196.         rpcHdrPtr->serverID < NET_NUM_SPRITE_HOSTS) {
  197.         char    addrBuffer[128];
  198.         Net_HdrDestString(interPtr->netType, protocol,headerPtr, 128, 
  199.             addrBuffer);
  200.         printf("Warning: Rpc_Dispatch, wrong server ID %d\n",
  201.             rpcHdrPtr->serverID);
  202.         printf("\tRPC %d flags %x Client %d at address: %s\n",
  203.                rpcHdrPtr->command, rpcHdrPtr->flags,
  204.                rpcHdrPtr->clientID, addrBuffer);
  205.  
  206.         } else {
  207.         printf("Rpc_Dispatch: junk serverID %d from client %d\n",
  208.                 rpcHdrPtr->serverID,
  209.                 rpcHdrPtr->clientID);
  210.         }
  211.         return;
  212.     }
  213.  
  214.     rpcSrvStat.toServer++;
  215.  
  216.     /*
  217.      * Verify or initialize the sprite host id for the client
  218.      * (clientID) from the transport level source address.
  219.      * This doesn't usually kick in unless the client can't do reverse arp.
  220.      */
  221.     if ( ! ValidateClient(interPtr, protocol, headerPtr, rpcHdrPtr)) {
  222.         rpcSrvStat.invClient++;
  223.         return;
  224.     }
  225.  
  226.     /*
  227.      * Save sender's requested interfragment delay.
  228.      */
  229.     rpcDelay[rpcHdrPtr->clientID] = rpcHdrPtr->delay;
  230.     /*
  231.      * Match the input message to a server process.
  232.      */
  233.     if (Recov_HoldForRecovery(rpcHdrPtr->clientID, rpcHdrPtr->command)) {
  234.         srvPtr = (RpcServerState *) NIL;
  235.     } else {
  236.         srvPtr = RpcServerAlloc(rpcHdrPtr);
  237.     }
  238. #ifdef NOTDEF
  239.     srvPtr = RpcServerAlloc(rpcHdrPtr);
  240. #endif /* NOTDEF */
  241.     
  242.     if (srvPtr == (RpcServerState *)NIL) {
  243.         /*
  244.          * Is it okay to check this here?
  245.          */
  246.         if (rpcServiceEnabled) {
  247.         rpcSrvStat.noAlloc++;
  248.         if (rpcSendNegAcks) {
  249.             RpcServerDispatch(srvPtr, rpcHdrPtr);
  250.         }
  251.         }
  252.     } else {
  253.         RpcServerDispatch(srvPtr, rpcHdrPtr);
  254.     }
  255.     } else {
  256.     /*
  257.      * Get the channel for the packet.
  258.      */
  259.     register RpcClientChannel *chanPtr;
  260.  
  261.     rpcCltStat.toClient++;
  262.     if (rpcHdrPtr->channel < 0 ||
  263.         rpcHdrPtr->channel >= rpcNumChannels) {
  264.         rpcCltStat.badChannel++;
  265.         printf("Rpc_Dispatch: bad channel %d from clt %d rpc %d",
  266.            rpcHdrPtr->channel, rpcHdrPtr->clientID, rpcHdrPtr->command);
  267.         printf("Resetting network interface %s\n", interPtr->name);
  268.         Net_Reset(interPtr);
  269.     } else {
  270.         /*
  271.          * Save sender's requested interfragment delay,
  272.          * then dispatch to client process.
  273.          */
  274.         if (rpcHdrPtr->serverID < NET_NUM_SPRITE_HOSTS &&
  275.         rpcHdrPtr->serverID > 0) {
  276.         rpcDelay[rpcHdrPtr->serverID] = rpcHdrPtr->delay;
  277.         }
  278.         chanPtr = rpcChannelPtrPtr[rpcHdrPtr->channel];
  279.         if (ultra) {
  280.         printf("Calling RpcClientDispatch\n");
  281.         }
  282.         RpcClientDispatch(chanPtr, rpcHdrPtr);
  283.     }
  284.     }
  285. }
  286.  
  287.  
  288. /*
  289.  *----------------------------------------------------------------------
  290.  *
  291.  * RpcScatter --
  292.  *
  293.  *    Copy the data in the network buffers into the buffers
  294.  *    specified by the scatter vector.  This routine only works
  295.  *    on RPC messages.  It knows the RPC packet format:
  296.  *      The Rpc header, which includes the sizes of the next two parts.
  297.  *      The parameter area.
  298.  *      The data area.
  299.  *    The scatter vector lengths of the last two parts are used
  300.  *    as maximum buffer sizes.  The actual sizes of the parts is
  301.  *    taken from the rpc header.  This is done because the RPC system
  302.  *    preallocates buffers which are large enough to handle any message.
  303.  *
  304.  * Results:
  305.  *    None.
  306.  *
  307.  * Side effects:
  308.  *    The copy.
  309.  *
  310.  *----------------------------------------------------------------------
  311.  */
  312. void
  313. RpcScatter(rpcHdrPtr, bufferPtr)
  314.     register RpcHdr *rpcHdrPtr;        /* The Rpc Header as it sits in the
  315.                      * network's buffer.  The data follows
  316.                      * the header directly. */
  317.     RpcBufferSet *bufferPtr;        /* Specification of the buffers to
  318.                      * copy the message to. */
  319. {
  320.     register Address netBufPtr;        /* A pointer in to network buffer */
  321.     register int length;        /* Copying length */
  322.     int destLength;            /* length of destination buffers */
  323.  
  324.     netBufPtr = (Address)rpcHdrPtr;
  325.  
  326.     /*
  327.      * Copy the RPC header.
  328.      */
  329.     length = bufferPtr->rpcHdrBuffer.length;
  330.     bcopy(netBufPtr, bufferPtr->rpcHdrBuffer.bufAddr, length);
  331.     netBufPtr += length;
  332.     /*
  333.      * Copy the parameter and data areas.  Their sizes are in
  334.      * the RPC header.  Complain if either area is too large.
  335.      */
  336.     length = rpcHdrPtr->paramSize;
  337.     if (length != 0) {
  338.     destLength = bufferPtr->paramBuffer.length;
  339.     if (length + rpcHdrPtr->paramOffset > destLength) {
  340.         rpcCltStat.paramOverrun++;
  341.         printf("RpcScatter: rpc %d param size + off (%d + %d) > (%d)\n",
  342.                rpcHdrPtr->command, length, rpcHdrPtr->paramOffset,
  343.                destLength);
  344.         if (rpcHdrPtr->paramOffset < destLength) {
  345.         length = destLength - rpcHdrPtr->paramOffset;
  346.         } else {
  347.         length = 0;
  348.         }
  349.     }
  350.     bcopy(netBufPtr, bufferPtr->paramBuffer.bufAddr +
  351.                      rpcHdrPtr->paramOffset, length);
  352.     netBufPtr += rpcHdrPtr->paramSize;
  353.     }
  354.     length = rpcHdrPtr->dataSize;
  355.     if (length != 0) {
  356.     destLength = bufferPtr->dataBuffer.length;
  357.     if (length + rpcHdrPtr->dataOffset > destLength) {
  358.     /*
  359.      * The returned data is more than we expect.  One reason for
  360.      * this is that the Intel driver limits the size of the data area and
  361.      * parameter area to be 0, or to be greater than 12 bytes because
  362.      * of the Intel DMA hardware.
  363.      */
  364.         rpcCltStat.dataOverrun++;
  365.         if (rpcHdrPtr->dataOffset < destLength) {
  366.         length = destLength - rpcHdrPtr->dataOffset;
  367.         } else {
  368.         length = 0;
  369.         }
  370.     }
  371.     bcopy(netBufPtr, bufferPtr->dataBuffer.bufAddr + rpcHdrPtr->dataOffset,
  372.         length);
  373.     }
  374. }
  375.  
  376. /*
  377.  *----------------------------------------------------------------------
  378.  *
  379.  * ValidateClient --
  380.  *
  381.  *      Check the clientID field of an incoming Rpc request.  Invalid ID's
  382.  *      are screened out, and the special clientID of zero is overwritten
  383.  *      with the client's true sprite ID.  This is done by looking the
  384.  *      client's physical address up in a table with Net_AddrToID.  This
  385.  *      true sprite ID is propogated back to clients so they can determine
  386.  *      their own sprite ID.  This should be replaced by the use of
  387.  *    Reverse Arp on clients at boot time.
  388.  *
  389.  * Results:
  390.  *      FALSE if clientID is invalid or the physical address of the client
  391.  *      isn't in the table.  TRUE otherwise - this gurantees a valid
  392.  *      clientID in the RpcHdr.
  393.  *
  394.  * Side effects:
  395.  *      Muck with the header so that subsequent users of the RpcHdr see a
  396.  *      valid clientID field.
  397.  *
  398.  *----------------------------------------------------------------------
  399.  */
  400. static Boolean
  401. ValidateClient(interPtr, protocol, headerPtr, rpcHdrPtr)
  402.     Net_Interface *interPtr;    /* Network interface. */
  403.     int        protocol;    /* Network protocol of packet. */
  404.     Address    headerPtr;    /* Transport header. */
  405.     RpcHdr      *rpcHdrPtr;
  406. {
  407.     register int        clientID;
  408.     register Boolean        result = FALSE;
  409.  
  410.     clientID = rpcHdrPtr->clientID;
  411.  
  412.     if (clientID > 0 && clientID < NET_NUM_SPRITE_HOSTS) {
  413.     /*
  414.      * A potentially valid clientID.  We don't need to
  415.      * save the client's transport address because the
  416.      * we can get that from the saved request message.
  417.      */
  418.     result = TRUE;
  419.     } else if (clientID == 0) {
  420.     /*
  421.      * Look client's transport address up in our in core host table.
  422.      */
  423.     clientID = Net_HdrToID(interPtr->netType, protocol, headerPtr);
  424.         printf("Warning: RpcValidateClient had to set clientID %d\n", clientID);
  425.     if (clientID < 0) {
  426.         char    addrBuffer[128];
  427.         /*
  428.          * Should invoke Reverse ARP to find out the Sprite ID.
  429.          */
  430.         Net_HdrDestString(interPtr->netType, protocol, headerPtr, 128, 
  431.         addrBuffer);
  432.         printf("Client at unknown address: %s\n", addrBuffer);
  433.         result = FALSE;
  434.     } else {
  435.         rpcHdrPtr->clientID = clientID;
  436.         result = TRUE;
  437.     }
  438.     } else {
  439.     result = FALSE;
  440.     printf("Invalid Client Sprite ID (%d)\n", clientID);
  441.     }
  442.     return(result);
  443. }
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * VersionMismatch --
  449.  *
  450.  *    This is called upon reciept of a packet with a bad RPC version
  451.  *    number.  This routine keeps a short list of offending hosts,
  452.  *    and will print out a warning about each one it encounters.
  453.  *
  454.  * Results:
  455.  *    None.
  456.  *
  457.  * Side effects:
  458.  *    This adds items to its versionList.
  459.  *
  460.  *----------------------------------------------------------------------
  461.  */
  462. static int numVersions = 0;
  463.  
  464. #define ADDR_LEN    40
  465. typedef struct {
  466.     Net_Interface    *interPtr;    /* Network interface. */
  467.     int protocol;            /* The packet protocol. */
  468.     int count;                /* Count of mismatches */
  469.     char sourceAddr[ADDR_LEN];        /* Storage for source addr string */
  470. } VersionRecord;
  471.  
  472. #define NUM_VERSIONS    4
  473. static VersionRecord versionList[NUM_VERSIONS];
  474.  
  475. static void
  476. VersionMismatch(interPtr, protocol, headerPtr, rpcHdrPtr, packetLength)
  477.     Net_Interface *interPtr;    /* Network interface. */
  478.     int        protocol;    /* Network protocol of packet. */
  479.     Address    headerPtr;    /* Pointer to transport header. */
  480.     RpcHdr    *rpcHdrPtr;    /* RPC header of packet. */
  481.     int        packetLength;    /* Size of RPC packet. */
  482. {
  483.     char addrBuffer[ADDR_LEN];
  484.     int i;
  485.     char *type;
  486.     char *proto;
  487.  
  488.     /*
  489.      * Get a string value for the sender of the packet and see if
  490.      * we've already gotten a bad packet from this host.
  491.      */
  492.     Net_HdrDestString(interPtr->netType, protocol, headerPtr, ADDR_LEN, 
  493.         addrBuffer);
  494.  
  495.     for (i=0 ; i<numVersions ; i++) {
  496.     if (strcmp(versionList[i].sourceAddr, addrBuffer) == 0) {
  497.         versionList[i].count++;
  498.         return;
  499.     }
  500.     }
  501.     if (numVersions >= NUM_VERSIONS) {
  502.     /*
  503.      * Bail out if we don't have room in the versionList.
  504.      * Alternatively we could replace an entry in the versionList.
  505.      */
  506.     return;
  507.     }
  508.  
  509.     switch(interPtr->netType) {
  510.     case NET_NETWORK_ETHER: 
  511.         type = "ether";
  512.         break;
  513.     default:
  514.         type = "unknown network type";
  515.         break;
  516.     }
  517.     switch(protocol) {
  518.     case NET_PROTO_RAW:
  519.         proto = "raw";
  520.         break;
  521.     case NET_PROTO_INET:
  522.         proto = "inet";
  523.         break;
  524.     default:
  525.         proto = "unknown network protocol";
  526.         break;
  527.     }
  528.     printf("RPC Version mismatch: %x not %x from %s %s %s",
  529.     rpcHdrPtr->version, rpc_NativeVersion, type, proto, addrBuffer);
  530.     if (rpcHdrPtr->clientID > 0 && rpcHdrPtr->clientID < NET_NUM_SPRITE_HOSTS) {
  531.     printf(" clientID %d\n", rpcHdrPtr->clientID);
  532.     } else {
  533.     printf("\n");
  534.     }
  535.     versionList[numVersions].count = 1;
  536.     versionList[numVersions].protocol = protocol;
  537.     versionList[numVersions].interPtr = interPtr;
  538.     (void) strncpy(versionList[numVersions].sourceAddr, addrBuffer, ADDR_LEN);
  539.     numVersions++;
  540.  
  541.     return;
  542. }
  543.